package com.hack4jp.hackearthquakes;

import java.util.List;
import java.util.Locale;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

public class LocationMapActivity  extends MapActivity {
	
	public static final double NUM_MILLION = 1e6;	
	public static final double DEFAULT_LATITUDE = 35.681382;
	public static final double DEFAULT_LONGITUDE = 139.766084;	
	
	private static final int
		MSG_SEARCH_COMPLETED = 1,
		MSG_SEARCH_ERROR = -1;	
	
    private Geocoder _geocoder;
	
    private MapView _mapView = null;
    private LocationMapOverlay _overlay = null;
    private Button _buttonSetting = null;
    private Button _buttonSearch = null;
    private EditText _editSearch = null;
    private TextView _txtLocation = null;
    
    private static ProgressDialog _dialogStatus = null;
    private Thread _threadSearch = null;    
    
    public MapView map() {
    	return _mapView;
    }
    
    public Geocoder geo() {
    	return _geocoder;
    }
    
    public void setLocationText(String s) {
    	if (_txtLocation == null)
    		return;
    	
    	_txtLocation.setText(s);
    }
    
	public static double getGeocoderDouble(int lat) {
		return lat / LocationMapActivity.NUM_MILLION;
	}
    
    private Handler handler = new Handler() {
        public void handleMessage(Message msg){
        	if (msg.what == MSG_SEARCH_COMPLETED) {
        		Address address = (Address)msg.obj;
        		setLocation(address.getLatitude(), address.getLongitude());
                
        		_overlay.setMapCenter();
                _mapView.invalidate();
        	} else if (msg.what == MSG_SEARCH_ERROR) {
        		String strMsg = (String)msg.obj;
        		String strAlert = getString(R.string.alertsearchlocation);
        		showAlert(strAlert + "\n" + strMsg, null, null, null);
        	}
            hideStatusDialog();
        }
    };
    
    public static GeoPoint getGeoPoint(double latitude, double longitude) {
    	int int_latitude = (int)(latitude * NUM_MILLION);
    	int int_longitude = (int)(longitude * NUM_MILLION); 
    	
        GeoPoint gp = new GeoPoint(int_latitude, int_longitude);
        return gp;
    }
    
    private void setLocation(double latitude, double longitude)
    {
    	if (latitude == 0.0 && longitude == 0.0) {
    		latitude = DEFAULT_LATITUDE;
    		longitude = DEFAULT_LONGITUDE;
    	}
    	
        _overlay.setLocationPoint(getGeoPoint(latitude, longitude));
    }
    
    @Override
    public void onCreate(Bundle bundle) {
    	super.onCreate(bundle);
    	
    	_geocoder = new Geocoder(this, Locale.JAPAN);
    	
    	initializeViews();
        
        if (_mapView != null) {        	
        	if (_overlay == null){
        		// 回転するとonCreateが再度呼ばれるためnullの時だけ実行する
        		Resources res = getResources();
        		_overlay = new LocationMapOverlay(this);
            	_overlay.setLocationIcon(BitmapFactory.decodeResource(res, R.drawable.map_pin_32));
            	_mapView.getOverlays().add(_overlay);        		
            	
        		// 現在位置をセット
        		Intent i = getIntent();
        		double latitude = i.getDoubleExtra("latitude", 0.0);
        		double longitude = i.getDoubleExtra("longitude", 0.0);
        		setLocation(latitude, longitude);
        		
            	// ダブルタップすることで現在地を指定することを伝える
            	String msg = getString(R.string.maphint);
            	Toast.makeText(this, msg, Toast.LENGTH_LONG).show();       	
        	}
        	
            // 現在位置を地図の中心に移動
        	_mapView.setBuiltInZoomControls(false);
        	_overlay.setMapCenter();
        }
    }

	@Override
	protected void onDestroy() {	
		// 破棄
      	_mapView.getOverlays().remove(_overlay);
      	super.onDestroy();
	}    

    private void initializeViews() {
        setContentView(R.layout.locationmap);
        
        _mapView = (MapView)findViewById(R.id.mapview);
        if (_mapView != null) {
        	MapController c = _mapView.getController();
        	c.setZoom(15);
        }
        
    	_buttonSetting = (Button)findViewById(R.id.buttonSetting);
    	if (_buttonSetting != null)
    		_buttonSetting.setOnClickListener(onClickSettingListener);

    	_buttonSearch = (Button)findViewById(R.id.buttonSearch);
    	if (_buttonSearch != null)
    		_buttonSearch.setOnClickListener(onClickSearchListener);
   
    	_editSearch = (EditText)findViewById(R.id.editLocation);
    	_txtLocation = (TextView)findViewById(R.id.currentLocation);
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
   
    private View.OnClickListener onClickSettingListener = new View.OnClickListener() {
    	@Override
    	public void onClick(View v) {
    		Log.v("LocationMapActivity.onClickSettingListener", "onClick");
    		
    		GeoPoint center = _overlay.getLocationPoint();
            double latitude = (double)center.getLatitudeE6() / NUM_MILLION;
            double longitude = (double)center.getLongitudeE6() / NUM_MILLION;
            
    		Intent intent = new Intent();  
            intent.putExtra("latitude", latitude); 
            intent.putExtra("longitude", longitude);  
            setResult(RESULT_OK, intent); 
    		finish();
    	}
    };
    
    private View.OnClickListener onClickSearchListener = new View.OnClickListener() {
    	@Override
    	public void onClick(View v) {
    		Log.v("LocationMapActivity.onClickSearchListener", "onClick");
    		searchAddress();
    	}
    };
    
    private void showStatusDialog(String message)
    {
    	if (_dialogStatus == null)
    		_dialogStatus = new ProgressDialog(this);
    	
    	_dialogStatus.setMessage(message);
    	_dialogStatus.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    	_dialogStatus.show();
    }
    
    private void hideStatusDialog()
    {
    	if (_dialogStatus == null)
    		return;
    	
    	_dialogStatus.dismiss();
    	_dialogStatus = null;
    }
    
    private void searchAddress()
    {
    	String msg = getString(R.string.searching);
    	showStatusDialog(msg);

    	_threadSearch = new Thread() {
    		@Override
    		public void run() {
    			Message msg = null;
    			try {
    				List<Address> list = _geocoder.getFromLocationName(_editSearch.getText().toString(), 1);
    				Address address = list.get(0);
    				msg = new Message();
    				msg.what = MSG_SEARCH_COMPLETED;
    				msg.obj = address;
    				handler.sendMessage(msg);
    			} catch (Exception e) {
    				msg = new Message();
    				msg.what = MSG_SEARCH_ERROR;
    				msg.obj = e.getMessage();
    				handler.sendMessage(msg);
    			}
    		}
    	};
    	_threadSearch.start();
	}
    
	private void showAlert(String message, String caption,
			DialogInterface.OnClickListener onOK,
			DialogInterface.OnClickListener onCancel) {
		AlertDialog.Builder ab = new AlertDialog.Builder(this);

		if (caption != null)
			ab.setTitle(caption);

		ab.setMessage(message);

		ab.setPositiveButton("OK", onOK);

		if (onCancel != null) {
			ab.setNegativeButton("Cancel", onCancel);
		}

		AlertDialog alertDialog = ab.create();
		alertDialog.show();
	}
}
